package com.bocloud.cmp.service.app.monitor;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.app.resource.OpenshiftMonitor;
import com.bocloud.common.http.HttpClient;
import com.bocloud.common.model.BaseResult;
import com.bocloud.common.model.Result;
import com.bocloud.common.utils.ListTool;
/**
 * @author Zaney
 * @data:2017年4月7日
 * @describe:容器平台监控client类
 */
@Repository("kubernetesOpenshiftMonitorClient")
public class KubernetesOpenshiftMonitorClient {
	private static Logger logger = LoggerFactory.getLogger(KubernetesOpenshiftMonitorClient.class);
	private HttpClient httpClient;

	public void setHttpClient(HttpClient httpClient) {
		this.httpClient = httpClient;
	}

	//*==========================cpu/memory/network 监控数据信息格式处理====================================*//
	
	public JSONObject memoryMonitor(OpenshiftMonitor monitor){
		JSONObject data = new JSONObject();
		JSONObject jsonObject = new JSONObject();
		JSONArray values = new JSONArray();
		// 1、获取memory监控
		JSONObject memoryObject = new JSONObject();
		JSONObject memoryMonitor = getMemoryMonitor(monitor);
		memoryObject.put("name", "Memory");
		memoryObject.put("data", memoryMonitor.get("memorys"));
		values.add(memoryObject);
		jsonObject.put("keys", memoryMonitor.get("dates"));// 时间轴
		jsonObject.put("values", values);
		data.put("MEMORY", jsonObject);
		data.put("type", "MEMORY");
		return data;
	}
	public JSONObject cpuMonitor(OpenshiftMonitor monitor){
		JSONObject data = new JSONObject();
		JSONObject jsonObject = new JSONObject();
		JSONArray values = new JSONArray();
		// 1、获取cpu监控
		JSONObject cpuObject = new JSONObject();
		JSONArray cpuMonitor = getCpuMonitor(monitor);
		cpuObject.put("name", "CPU");
		cpuObject.put("data", cpuMonitor);
		values.add(cpuObject);
		jsonObject.put("values", values);
		data.put("CPU", jsonObject);
		data.put("type", "CPU");
		return data;
	}
	public JSONObject networkRxMonitor(OpenshiftMonitor monitor){
		JSONObject data = new JSONObject();
		// 1、获取networkRx监控，Received
		JSONObject networkRx = new JSONObject();
		JSONArray networkMonitorRx = getNetworkRxMonitor(monitor);
		networkRx.put("name", "Received");
		networkRx.put("data", networkMonitorRx);
		data.put("NETWORKRX", networkRx);
		data.put("type", "NETWORKRX");
		return data;
	}
	public JSONObject networkTxMonitor(OpenshiftMonitor monitor){
		JSONObject data = new JSONObject();
		// 1、获取networkTx监控，Send
		JSONObject networkTx = new JSONObject();
		JSONArray networkMonitorTx = getNetworkTxMonitor(monitor);
		networkTx.put("name", "Send");
		networkTx.put("data", networkMonitorTx);
		data.put("NETWORKTX", networkTx);
		data.put("type", "NETWORKTX");
		return data;
	}
	
	// *=============================pod的cpu/memory/network监控信息数据处理============================*//
	
	private JSONObject getMemoryMonitor(OpenshiftMonitor memoryMonitor) {
		JSONObject object = new JSONObject();
		JSONArray memorys = new JSONArray();
		JSONArray dates = new JSONArray();
		BaseResult<JSONArray> monitorMessage = null;
		try {
			monitorMessage = getMonitorMessage(memoryMonitor);
			if (monitorMessage.isSuccess()) {
				// 获取存储信息
				JSONArray messages = monitorMessage.getData();
				for (Object message : messages) {
					JSONObject obj = JSONObject.parseObject(message.toString());
					// 统计时间
					if (obj.containsKey("start")) {
						dates.add(obj.getString("start"));
					}
					// 计算内存信息
					if (obj.containsKey("avg")) {
						BigDecimal avg = new BigDecimal(obj.getString("avg"));
						avg = avg.divide(new BigDecimal(1000).multiply(new BigDecimal(1000)), 2, RoundingMode.HALF_UP);
						memorys.add(avg);
					}
				}
			}
			if (monitorMessage.isSuccess() && ListTool.isEmpty(memorys)) {
				for (int j = 0; j < 30; j++) {
					memorys.add(0.00);
				}
			}
			logger.warn(monitorMessage.getMessage());
			object.put("dates", dates);
			object.put("memorys", memorys);
		} catch (Exception e) {
			logger.error("初步获取memory监控信息失败 ", e);
		}
		return object;
	}

	private JSONArray getCpuMonitor(OpenshiftMonitor cpuMonitor) {
		JSONArray cpus = new JSONArray();
		BaseResult<JSONArray> monitorMessage = null;
		try {
			monitorMessage = getMonitorMessage(cpuMonitor);
			if (monitorMessage.isSuccess()) {
				JSONArray messages = monitorMessage.getData();
				for (int i = 1; i < messages.size(); i++) {
					JSONObject firstCpu = JSONObject.parseObject(messages.get(i - 1).toString());
					JSONObject secondCpu = JSONObject.parseObject(messages.get(i).toString());
					if (firstCpu.containsKey("avg") && secondCpu.containsKey("avg")) {
						BigDecimal firstAvg = new BigDecimal(firstCpu.getString("avg"));
						BigDecimal secondAvg = new BigDecimal(secondCpu.getString("avg"));
						// monitor.getBucketDuration()时间单位ms
						// ,乘以1000000转换成ns,与avg的单位（ns）符合
						BigDecimal time = new BigDecimal(cpuMonitor.getBucketDuration()).multiply(new BigDecimal(1000000));
						// 计算cpu监控信息
						BigDecimal cpu = (secondAvg.subtract(firstAvg).multiply(new BigDecimal(1000))).divide(time, 0,
								RoundingMode.HALF_UP);
						cpus.add(cpu.abs());
					}
				}
			}
			if (monitorMessage.isSuccess() && ListTool.isEmpty(cpus)) {
				for (int j = 0; j < 30; j++) {
					cpus.add(0.00);
				}
			}
			logger.warn(monitorMessage.getMessage());
		} catch (Exception e) {
			logger.error("初步获取cpu监控信息失败 ", e);
		}
		return cpus;
	}

	private JSONArray getNetworkTxMonitor(OpenshiftMonitor netTxMonitor) {
		JSONArray networks = new JSONArray();
		BaseResult<JSONArray> networkTx = null;
		try {
			networkTx = getMonitorMessage(netTxMonitor);
			// tx
			if (networkTx.isSuccess()) {
				JSONArray objTx = networkTx.getData();
				for (int i = 1; i < objTx.size(); i++) {
					JSONObject firstObj = JSONObject.parseObject(objTx.get(i - 1).toString());
					JSONObject secondObj = JSONObject.parseObject(objTx.get(i).toString());
					if (firstObj.containsKey("avg") && secondObj.containsKey("avg")) {
						BigDecimal firstAvg = new BigDecimal(firstObj.getString("avg")).divide(new BigDecimal(1000));
						BigDecimal secondAvg = new BigDecimal(secondObj.getString("avg")).divide(new BigDecimal(1000));
						// 计算网络数据信息
						BigDecimal time = new BigDecimal(netTxMonitor.getBucketDuration()).divide(new BigDecimal(1000), 2,
								RoundingMode.HALF_UP);
						BigDecimal net = secondAvg.subtract(firstAvg).divide(time, 2, RoundingMode.HALF_UP);
						networks.add(net.abs());
					}
				}
			}
			if (networkTx.isSuccess() && ListTool.isEmpty(networks)) {
				for (int j = 0; j < 30; j++) {
					networks.add(0.00);
				}
			}
			logger.warn(networkTx.getMessage());
		} catch (Exception e) {
			logger.error("初步获取network监控信息失败 ", e);
		}
		return networks;
	}

	private JSONArray getNetworkRxMonitor(OpenshiftMonitor netRxMonitor) {
		JSONArray networks = new JSONArray();
		BaseResult<JSONArray> networkRx = null;
		try {
			networkRx = getMonitorMessage(netRxMonitor);
			// rx
			if (networkRx.isSuccess()) {
				JSONArray objRx = networkRx.getData();
				for (int i = 1; i < objRx.size(); i++) {
					JSONObject firstObj = JSONObject.parseObject(objRx.get(i - 1).toString());
					JSONObject secondObj = JSONObject.parseObject(objRx.get(i).toString());
					if (firstObj.containsKey("avg") && secondObj.containsKey("avg")) {
						BigDecimal firstAvg = new BigDecimal((firstObj.getString("avg"))).divide(new BigDecimal(1000));
						BigDecimal secondAvg = new BigDecimal((secondObj.getString("avg"))).divide(new BigDecimal(1000));
						// 计算网络数据信息
						BigDecimal time = new BigDecimal(netRxMonitor.getBucketDuration()).divide(new BigDecimal(1000), 2,
								RoundingMode.HALF_UP);
						BigDecimal net = secondAvg.subtract(firstAvg).divide(time, 2, RoundingMode.HALF_UP);
						networks.add(net.abs());
					}
				}
			}
			if (networkRx.isSuccess() && ListTool.isEmpty(networks)) {
				for (int j = 0; j < 30; j++) {
					networks.add(0.00);
				}
			}
			logger.warn(networkRx.getMessage());
		} catch (Exception e) {
			logger.error("初步获取network监控信息失败 ", e);
		}
		return networks;
	}

	
	/**
	 * url
	 * @param monitor
	 * @return
	 */
	private BaseResult<JSONArray> getMonitorMessage(OpenshiftMonitor monitor) {
		String url = null;
		try {
			HashMap<String, Object> hashMap = new HashMap<String, Object>();
			hashMap.put("Authorization", "Bearer " + monitor.getToken());
			hashMap.put("Hawkular-Tenant", monitor.getNamespace());
			if (!"node".equals(monitor.getType())) {
				url = "https://" + monitor.getDomainName() + "/hawkular/metrics/" + monitor.getAccess() + "/data?"
						+ "stacked=true&tags=descriptor_name:" + monitor.getDescripteName() + ",type:"
						+ monitor.getType() + ",pod_name:" + monitor.getResourceName() + "&bucketDuration="
						+ monitor.getBucketDuration() + "ms&start=" + monitor.getStartTime();
			} else {
				url = "https://" + monitor.getDomainName() + "/hawkular/metrics/" + monitor.getAccess() + "/data?"
						+ "stacked=true&tags=descriptor_name:" + monitor.getDescripteName() + ",type:"
						+ monitor.getType() + ",nodename:" + monitor.getResourceName() + "&bucketDuration="
						+ monitor.getBucketDuration() + "ms&start=" + monitor.getStartTime();
			}
			logger.info(monitor.getResourceName()+"-->"+monitor.getResourceType()+"访问的url: "+url);
			Result result = httpClient.get(hashMap, null, url);
			if (result.isSuccess()) {
				JSONArray messages = JSONObject.parseArray(result.getMessage());
				return new BaseResult<JSONArray>(true, "获取服务端信息成功", messages);
			} else {
				return new BaseResult<JSONArray>(false, "获取服务端监控信息失败");
			}
		} catch (Exception e) {
			logger.error("httpClient连接失败，获取"+monitor.getResourceType()+"监控信息异常,访问的url路径 ["+url+"]", e);
			return new BaseResult<JSONArray>(false, "httpClient连接失败，获取"+monitor.getResourceType()+"监控信息异常");
		}
	}
	
	/**
	 * 线程池任务
	 * @param monitors
	 * @return
	 * @throws Exception
	 */
	public List<JSONObject> batch(List<OpenshiftMonitor> monitors) throws Exception {
		ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
		CompletionService<BaseResult<JSONObject>> completionService = new ExecutorCompletionService<>(executor);
		if (ListTool.isEmpty(monitors)) {
			return null;
		}
		for (OpenshiftMonitor monitor : monitors) {
			KubernetesMonitorTask task = new KubernetesMonitorTask(monitor);
			completionService.submit(task);
		}
		List<JSONObject> objectList = new ArrayList<JSONObject>();
		int completeTask = 0;
		int timeout = 1000 * 60 * 10;
		long begingTime = System.currentTimeMillis();
		while (completeTask < monitors.size()) {
			Future<BaseResult<JSONObject>> take = completionService.take();
			if (null != take) {
				BaseResult<JSONObject> result = take.get();
				if (result.isSuccess()) {
					objectList.add((JSONObject) result.getData());
				}
				completeTask++;
				if (System.currentTimeMillis() - begingTime > timeout) {
					break;
				}
			}
		}
		executor.shutdown();
		return objectList;
	}
	
	
}
